package com.fclub.push.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javapns.Push;
import javapns.devices.Device;
import javapns.devices.implementations.basic.BasicDevice;
import javapns.notification.PushNotificationPayload;
import javapns.notification.PushedNotification;
import javapns.notification.ResponsePacket;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.fclub.push.dao.PushDao;
import com.fclub.push.tool.ApplicationConfig;
import com.fclub.push.vo.PushDeviceVo;
import com.fclub.push.vo.PushInfoVo;

/**
 * 线程池执行任务
 * 
 * @author penghui.li
 * 
 */
public class ApplePushInfo {
	private Log logger = LogFactory.getLog(this.getClass());
	private PushDao pushDao;
	private String keystore = ApplicationConfig.getApplicationConfig().getPropertie("push.iphone.keystore", "d:/apns.p12");
	private String password = ApplicationConfig.getApplicationConfig().getPropertie("push.iphone.password", "123456");
	private boolean production = ApplicationConfig.getApplicationConfig().getPropertie("push.iphone.production", "0").equals("0") ? true : false;
	private int threads = Integer.parseInt(ApplicationConfig.getApplicationConfig().getPropertie("push.iphone.threads.count", "30"));
	
	public ApplePushInfo() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
		pushDao = (PushDao) ctx.getBean("pushDao");
	}

	public static void main(String[] args) {
		try {
			new ApplePushInfo().push();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@SuppressWarnings({ "rawtypes", "unused", "unchecked" })
	public void push() {
		long startTm = System.currentTimeMillis();
		try {
			//对apple反馈的数据进行处理
			handleFeedback();
			Map map = new HashMap();
			//获得要发送的信息列表
			List<PushInfoVo> list = pushDao.queryPushInfoList(map);
			StringBuffer ids = new StringBuffer();
			List<PushDeviceVo> ulist = new ArrayList<PushDeviceVo>();
			for (PushInfoVo vo : list) {
				map.put("type", vo.getType());
				//获得要发送该信息的设备列表
				ulist = pushDao.queryPushUdidList(map);
				List<Device> li = new ArrayList<Device>();
				for (PushDeviceVo dVo : ulist) {
					Device device = new BasicDevice();
					device.setToken(dVo.getDeviceToken());
//					device.setToken("e4becddba633695c9e911f2e8709ce53d3c7af557ace4efc9ae2675a00ae6ab7");
					li.add(device);
				}
				startTm = System.currentTimeMillis();
				if (li.size() > 0) {
					send(li, vo.getInfo(), keystore, password, production);
				}
				logger.info("**********push:" + li.size() + "****************cost:[" + (System.currentTimeMillis() - startTm) + "]ms");
			}
			startTm = System.currentTimeMillis();
			//发送成功后批量更新信息的状态
			map.put("infoList", list);
			if(list != null && list.size()>0){
				pushDao.updatePushInfoStatus(list);
			}else{
				logger.info("*********infolist is null or this size is zero");
			}
			logger.info("**********update info:" + list.size() + "****************cost:[" + (System.currentTimeMillis() - startTm) + "]ms");
		} catch (Exception ex) {
			ex.printStackTrace();
			logger.info(ex.toString());
		}
	}

	/**
	 * 对apple反馈的数据进行处理
	 * @param devList
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void handleFeedback() {
		long startTm = System.currentTimeMillis();
		List<Device> feedBacklist = new ArrayList<Device>();
		try {
			feedBacklist = Push.feedback(keystore, password, production);
			logger.info("**********getFeedback:" + feedBacklist.size() + "****************cost:[" + (System.currentTimeMillis() - startTm) + "]ms");
			Map map = new HashMap();
			map.put("devList", feedBacklist);
			
//			/**********test start*************/
//			Device device = new BasicDevice();
//			device.setToken("cee9fdb1188bdc27177065db15639af903d7f2b474041b02e4ddd303bcaca509");
//			feedBacklist.add(device);
//			/**********test end*************/
			
			startTm = System.currentTimeMillis();
			if(feedBacklist != null && feedBacklist.size()>0){
				pushDao.updateDeviceStatus(feedBacklist);
			}else{
					logger.info("*********feedBacklist is null or this size is zero");	
			}
			logger.info("**********update Device:" + feedBacklist.size() + "****************cost:[" + (System.currentTimeMillis() - startTm) + "]s");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.info(e.toString());
		} 
		

	}

	/**
	 * 发送
	 * @param devices
	 * @param message
	 * @param keystore
	 * @param password
	 * @param production
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	public void send(List<Device> devices, String message, Object keystore,
			String password, boolean production) throws Exception {
		PushNotificationPayload payload = PushNotificationPayload.alert(message);
		List<PushedNotification> notifications = Push.payload(payload,keystore, password, production, threads, devices);
		int successNum = 0;
		int failedNum = 0;
        for (PushedNotification notification : notifications) {
                if (notification.isSuccessful()) {
//                        System.out.println("Push notification sent successfully to: " +
//                                                        notification.getDevice().getToken());
                        
                        successNum++;
                } else {
                		failedNum++;
                        String invalidToken = notification.getDevice().getToken();
                        logger.info("**********Push notification sent failed to:token->[" + invalidToken+"]");
                        Exception theProblem = notification.getException();
//                        theProblem.printStackTrace();  
                        ResponsePacket theErrorResponse = notification.getResponse();
                        if (theErrorResponse != null) {
//                                System.out.println(theErrorResponse.getMessage());
//                                logger.info("theErrorResponse.getMessage()");
                        }
                }
        }
        logger.info("**********Push message:"+message+"**** total->["+devices.size()+"]***success->["+successNum+"]***failed["+failedNum+"]");
	}

	public PushDao getPushDao() {
		return pushDao;
	}

	public void setPushDao(PushDao pushDao) {
		this.pushDao = pushDao;
	}
}
